home *** CD-ROM | disk | FTP | other *** search
/ Collection of Tools & Utilities / Collection of Tools and Utilities.iso / c / c_flow.zip / CFLOWX.C < prev    next >
Text File  |  1985-06-24  |  24KB  |  1,079 lines

  1. /*    CFLOWX.C: cflow cross-reference utility for function/macro calls
  2. **
  3. **    Copyright (c) 1985 by:
  4. **
  5. **        Lawrence R. Steeger
  6. **        1009 North Jackson
  7. **        Milwaukee, Wisconsin 53202
  8. **        414-277-8149
  9. */
  10.  
  11. #include <stdio.h>            /* CI-C86 header        */
  12.  
  13. #define    VOID int
  14.  
  15. /*    external functions        */
  16.  
  17. extern    VOID abort();
  18. extern    char *alloc();
  19. extern    VOID exit();
  20. extern    int fclose();
  21. extern    char *fgets();
  22. extern    FILE *fopen();
  23. extern    VOID fprintf();
  24. extern    VOID free();
  25. extern    char *lower();
  26. extern    VOID printf();
  27. extern    VOID qsort();
  28. extern    char *realloc();
  29. extern    VOID sprintf();
  30. extern    int sscanf();
  31. extern    char *strcat();
  32. extern    int strcmp();
  33. extern    char *strcpy();
  34. extern    int strlen();
  35. extern    int strncmp();
  36. extern    int tolower();
  37.  
  38. #include "cflowx.h"            /* CFLOW/CFLOWX header        */
  39.  
  40. #define    VERSION    85
  41. #define    RELEASE    06
  42. #define    MODIFIC    20
  43.  
  44. #define    outinfo(S) fputs(S, stdout)
  45.  
  46. outlogo()
  47. {
  48.     fprintf(stdout, "\n%s V%02d.%02d.%02d - %s",
  49.         "CFLOWX",
  50.         VERSION, RELEASE, MODIFIC,
  51.         "cflow cross-reference generator");
  52.     outinfo("\nCopyright (c) 1985 by Lawrence R. Steeger\n");
  53. }
  54.  
  55. outhelp()
  56. {
  57.     outinfo("\nusage: cflowx [-[efimr]] infile [>outfile]");
  58.     outinfo("\n note: infile is created by the");
  59.     outinfo(" CFLOW utility using the -x flag\n");
  60.     outinfo("\nreports: -e    function/macro external definition report");
  61.     outinfo("\n         -f    path\\file name report");
  62.     outinfo("\n         -i    function/macro internal definition report");
  63.     outinfo("\n         -m    macro name cross-reference report");
  64.     outinfo("\n         -r    function name cross-reference report");
  65.     outinfo("\n   note: The order of the specified [efimr] flags will");
  66.     outinfo("\n         be the order that the reports will generated in.");
  67. }
  68.  
  69. #define    OUTHDR    0            /* start output header        */
  70. #define    OUTUPD    1            /* update output array        */
  71. #define    OUTFLSH    2            /* flush output line        */
  72. #define    OUTCLR    3            /* clear output line        */
  73.  
  74. typedef    struct _xref {            /* cross-reference record    */
  75.  
  76.     struct _xref *_related;        /* related XREF chain        */
  77.  
  78.     unsigned char _dup;        /* duplicate entry flag        */
  79.  
  80.     int _fnmbr,            /* file name number        */
  81.         _level,            /* {...} nest level number    */
  82.         _line;            /* line number            */
  83.  
  84.     unsigned int _str;        /* record data string offset    */
  85.  
  86.     } XREF;
  87.  
  88. static    XREF *xref = NULL,        /* XREF element pointers    */
  89.          *xref1 = NULL,
  90.          *xref2 = NULL,
  91.          *xref3 = NULL,
  92.          *xref4 = NULL,
  93.          *xchain = NULL;
  94.  
  95. /*    useability macros for XREF    */
  96.  
  97. #define    related xref->_related
  98. #define    dup xref->_dup
  99. #define    fnmbr xref->_fnmbr
  100. #define    level xref->_level
  101. #define    line xref->_line
  102. #define    str xref->_str
  103.  
  104. #define    related1 xref1->_related
  105. #define    dup1 xref1->_dup
  106. #define    fnmbr1 xref1->_fnmbr
  107. #define    level1 xref1->_level
  108. #define    line1 xref1->_line
  109. #define    str1 xref1->_str
  110.  
  111. #define    related2 xref2->_related
  112. #define    dup2 xref2->_dup
  113. #define    fnmbr2 xref2->_fnmbr
  114. #define    level2 xref2->_level
  115. #define    line2 xref2->_line
  116. #define    str2 xref2->_str
  117.  
  118. #define    related3 xref3->_related
  119. #define    dup3 xref3->_dup
  120. #define    fnmbr3 xref3->_fnmbr
  121. #define    level3 xref3->_level
  122. #define    line3 xref3->_line
  123. #define    str3 xref3->_str
  124.  
  125. #define    related4 xref4->_related
  126. #define    dup4 xref4->_dup
  127. #define    fnmbr4 xref4->_fnmbr
  128. #define    level4 xref4->_level
  129. #define    line4 xref4->_line
  130. #define    str4 xref4->_str
  131.  
  132. #define    relxc xchain->_related
  133. #define    dupxc xchain->_dup
  134. #define    fnmbrxc xchain->_fnmbr
  135. #define    levelxc xchain->_level
  136. #define    linexc xchain->_line
  137. #define    strxc xchain->_str
  138.  
  139. typedef    struct _rqueue {        /* xref record queue header    */
  140.  
  141.     XREF **__xref;            /* XREF record queue pointer    */
  142.     unsigned char _sorted;        /* sorted queue flag        */
  143.     unsigned int _total,        /* offset counter        */
  144.              _index;        /* offset index            */
  145.  
  146.     } RQUEUE;
  147.  
  148. static    RQUEUE rqueue[HIGHKEY];        /* xref record queue headers    */
  149.  
  150. static    int rkey = 0,            /* xref record queue keys    */
  151.         rkey1 = 0,
  152.         rkey2 = 0;
  153.  
  154. /*    useability macros for RQUEUE    */
  155.  
  156. #define    pxref rqueue[rkey].__xref
  157. #define    sorted rqueue[rkey]._sorted
  158. #define    total rqueue[rkey]._total
  159. #define    index rqueue[rkey]._index
  160.  
  161. #define    pxref1 rqueue[rkey1].__xref
  162. #define    sorted1 rqueue[rkey1]._sorted
  163. #define    total1 rqueue[rkey1]._total
  164. #define    index1 rqueue[rkey1]._index
  165.  
  166. #define    pxref2 rqueue[rkey2].__xref
  167. #define    sorted2 rqueue[rkey2]._sorted
  168. #define    total2 rqueue[rkey2]._total
  169. #define    index2 rqueue[rkey2]._index
  170.  
  171. static    unsigned char *strings = NULL;    /* character strings buffer    */
  172. static    unsigned int stringl = 0;    /* character strings length    */
  173.  
  174. static    char *invrec =            /* standard input error format    */
  175.          "invalid record %s- %d: \"%s";
  176.  
  177. static    int reportc = 0;        /* report function counter    */
  178. static    PFI *(reports) = NULL;        /* report function pointers    */
  179.  
  180. /*    mainline            */
  181.  
  182. main(argc, argv)
  183. int argc;
  184. unsigned char **argv;
  185. {
  186.     int i, j;
  187.  
  188.     outlogo();            /* display utility logo        */
  189.  
  190.     if (argc < 2) {            /* too few arguments        */
  191.         outhelp();
  192.         exit(1);        /* exit abnormal        */
  193.     }
  194.  
  195.     for (rkey = 0; rkey < HIGHKEY; rkey++) { /* reset queue headers    */
  196.         pxref  = NULL;
  197.         sorted = FALSE;
  198.         total  = 0;
  199.         index  = 0;
  200.     }
  201.  
  202.     for (i = 1; i < argc; i++) {    /* process -flags        */
  203.         if (*argv[i] == '-') {
  204.             flags(argv[i]);
  205.             for (j = i--, --argc; j < argc; j++)
  206.                 argv[j] = argv[j+1];
  207.         }
  208.     }
  209.  
  210.     if (argc < 2) {            /* no filename specified !    */
  211.         outhelp();
  212.         exit(1);        /* exit abnormal        */
  213.     }
  214.  
  215.     buildq(argv[1]);        /* build CFLOWX record queues    */
  216.  
  217.     dupfile();            /* detect duplicate files    */
  218.  
  219.     for (i = 0; i < reportc; i++)    /* generate CFLOWX reports    */
  220.         (*(reports[i]))();
  221.  
  222.     exit(0);            /* exit normal            */
  223. }
  224.  
  225. /*    process command line flags                    */
  226.  
  227. flags(flag)
  228. unsigned char *flag;
  229. {
  230.     int i;
  231.  
  232.     PFI function;
  233.  
  234.     int reporte(),            /* function/macro external    */
  235.         reportf(),            /* path\file name        */
  236.         reporti(),            /* function/macro internal    */
  237.         reportm(),            /* macro cross_reference    */
  238.         reportr();            /* function cross_reference    */
  239.  
  240.     for (i = 0; flag[++i];) {        /* scan all characters    */
  241.  
  242.         function = NULL;
  243.  
  244.         switch (tolower(flag[i])) {    /* set any valid flag    */
  245.  
  246.         case 'e':        /* function/macro external    */
  247.             function = reporte;
  248.             break;
  249.  
  250.         case 'f':        /* path\file name        */
  251.             function = reportf;
  252.             break;
  253.  
  254.         case 'i':        /* function/macro internal    */
  255.             function = reporti;
  256.             break;
  257.  
  258.         case 'm':        /* macro cross_reference    */
  259.             function = reportm;
  260.             break;
  261.  
  262.         case 'r':        /* function cross_reference    */
  263.             function = reportr;
  264.             break;
  265.  
  266.         default:
  267.             abort("Unknown flag: '%c'\n", flag[i]);
  268.             break;
  269.         }
  270.  
  271.         if (function != NULL) {
  272.             reports = realloc(reports, (sizeof(PFI)*(reportc+1)));
  273.             if (reports == NULL)
  274.                 abort("REALLOC - reports");
  275.             reports[reportc++] = function;
  276.         }
  277.     }
  278.  
  279.     flag[0] = EOS;                /* terminate flag    */
  280. }
  281.  
  282. /*    build CFLOWX record queues                    */
  283.  
  284. buildq(filename)
  285. unsigned char *filename;
  286. {
  287.     unsigned char *cp,
  288.               string[MAXBUF];
  289.  
  290.     unsigned int stradd();        /* add string to char buffer    */
  291.  
  292.     int currec,            /* current input record        */
  293.         crelxkey,            /* current related base key    */
  294.         i,
  295.         j;
  296.  
  297.     FILE *fptr;            /* input file pointer        */
  298.  
  299.     XREF *crelated;            /* related XREF base pointer    */
  300.  
  301.     if ((fptr = fopen(filename, "r+")) == NULL) /* open input file    */
  302.         abort("FOPEN - %s\n", filename);
  303.  
  304.     currec = 0;            /* start record counter        */
  305.     crelated = NULL;        /* clear related chain base    */
  306.  
  307.     while (1) {            /* scan XREF input        */
  308.  
  309.         if (fgets(string,MAXBUF,fptr)==FALSE) /* get record    */
  310.             break;
  311.  
  312.         xref = alloc(sizeof(XREF));    /* next XREF element    */
  313.  
  314.         ++currec;            /* update line count    */
  315.  
  316.         /*    scan for standard fields             */
  317.  
  318.         if ((i=sscanf(string,
  319.                 cxref((MAXFLDS-1)),
  320.                 &rkey,
  321.                 &fnmbr,
  322.                 &level,
  323.                 &line)
  324.             ) != ((MAXFLDS-1)*2)) {
  325.             printf("sscanf(%d)\n", i);
  326.             abort(invrec, "sscanf ", currec, string);
  327.         }
  328.  
  329.         if (rkey >= HIGHKEY)        /* validate record key    */
  330.             abort(invrec, "type ", currec, string);
  331.  
  332.         /*    skip over standard fields            */
  333.  
  334.         for (i=j=0; j != (MAXFLDS-1) && string[i] != RS; i++)
  335.             if (string[i] == U